'''函数重写'''

# class MyList:
#     def __init__(self,iterator=[]):
#         self.num = [x for x in iterator]
#     def __repr__(self):
#         return "MyList(%r)" % self.num
#     def __abs__(self):
#         #返回一个新的MyList类型，其所有的元素是原来的元素都取绝对值
#         # return MyList([abs(x) for x in self.num])
#         # 使用生成器表达式，防止过多占用内存
#         return MyList((abs(x) for x in self.num))
#     # def __bool__(self):
#     #     print("被调用了")
#     #     return False
#     def __len__(self):
#         print("len被调用")
#         return len(self.num)
#
# L = [1,5,9,-3,-6,-8]#内建函数
# mylist = MyList([1,5,9,-3,-6,-8])#自定义
# # print(abs(L))#列表不支持绝对值运算
# print(abs(mylist))
#
# print(bool(L))
# print("~~~~~~~~~")
# print(bool(mylist))
# print("~~~~~~~~~")
#
# print(len(L))
# print(len(mylist))

# bool(obj)一般用作真值计算，优先调用__bool__,若果没有这个函数则会调用__len__,如果也没有__len__则返回True



# class MyList:
#     def __init__(self,iterator=None):
#         self.num = [x for x in iterator]
#
#     def __repr__(self):
#         return "MyList(%r)" % self.num
#
#     def __iter__(self):
#         return MyIterable(self.num)
#
# class MyIterable:
#     def __init__(self, ite_data):
#         self.ite_data = ite_data
#         self.index = 0
#
#     def __next__(self):
#         #每调用一个next，就返回一个值，这个值是num中的下一个
#         print("next被调用了")
#         if self.index >= len(self.ite_data):
#             raise StopIteration
#         i = self.ite_data[self.index]
#         self.index += 1
#         return i
#
# mylist = MyList([1,5,9])
# it = iter(mylist)
# print(next(it))


# class MyFun:
#     def __init__(self,data):
#         self.data = data
#     def __repr__(self):
#         return "Fibonacci numbers %d" % self.data
#     def __iter__(self):
#         return Fibonacci(self.data)
#
# class Fibonacci:
#     def __init__(self,n):
#         self.count = n
#         self.a = 0
#         self.b = 1
#         self.current_count = 0
#
#     def __iter__(self):
#         return self
#
#     def __next__(self):
#         if self.current_count > self.count:
#             raise StopIteration
#         i = self.a
#         # temp = self.b
#         # self.b = self.a + temp
#         # self.a = temp
#         self.a ,self.b = self.b,self.a + self.b
#         self.current_count += 1
#         return i
#
# fibonacci = Fibonacci(10)
# it = iter(fibonacci)
# print(next(it))
# print(next(it))

# L = [0,1]
# i=0
# while True:
#     n = int(L[i])
#     m = int(L[i+1])
#     x = n+m
#     L.append(x)
#     if i == 6:
#         break
#     i +=1
# print(L)



'''oop异常的处理'''
# try  except --用来捕获异常
# try  finally --不管发生异常与否，都要晚上的必要工作
# raise --用来触发异常
# assert --通过真值表达式，发出一个错误通知，AssertError
# with 表达式 [as 变量],表达式 [as 变量],表达式 [as 变量]...
# pass
# 作用：在一些访问资源的场景下（文件操作、数据库操作、线程锁）
#      确保在使用过程中，不管是否发生异常，都要进行的操作，如：释放资源


# class FileTest():
#     def __init__(self,filename):
#         self.filename = filename
#     def read_from_file(self):
#         with open(self.filename,'r') as f:
#             print(f.readline())
#
# filetest = FileTest("111.txt")
# filetest.read_from_file()



'''环境管理器'''
# 类中有__enter__和__exit__ 实例方法的类叫做环境管理器
# 能够使用with对于据进行管理的对象必须是环境管理器
# __enter__这个实例方法在进入with的时候被调用，并且返回又as变量管理的对象
# __exit__这个实例方法在离开with的时候被调用，而且可以通过相关的参数在离开时判断是否发生异常，以及异常的相关信

# class A():
#     #进入with的时候会自动执行
#     def __enter__(self):
#         #最终返回一个对象，这个对象会被赋值给as后的变量
#         return self
#     #离开with的时候会自动执行，通过参数判断是否发生异常
#     def __exit__(self, exc_type, exc_val, exc_tb):
#         #当离开时要做的事情，根据exc_type来处理具体的事情
#         #exc_val，具体的错误信息
#         #exc_tb 溯源
#         if exc_type is None:
#             print("离开了with，也没发生异常")
#         else:
#             print("离开with，但发生异常")
#             print("exc_type:", exc_type)
#             if exc_type == FileExistsError:
#                 print("文件找不到")
#             print("exc_val:", exc_val)
#             print("exc_tb:", exc_tb)
#
# with A() as a :
#     f = open("1235.txt")



'''对象的属性管理函数'''
# __dic__:字典的形式，存储了实例的属性
# __slots__:列表，限制了对象只能具备的属性，如果声明了这个__slots__，就没有__dic__属性了

# getattr(obj,name[,default]),从obj对象中获取名字为name属性，相当于 obj.name
# 如果没有这个属性，就会返回default的数据，如果default也没有，就会返回一个错误。

# class Car():
#     def __init__(self,color,brand):
#         self.color = color
#         self.brand = brand
#
#
# car = Car("黑色","haha")
#
# print(getattr(car,'color'))
# print(getattr(car,'brand'))
# # print(getattr(car,'prince'))#AttributeError: 'Car' object has no attribute 'prince'
# print(hasattr(car,'color'))#True
# print(hasattr(car,'prince'))#False
# delattr(car,'color')
# print(hasattr(car,'prince'))
# delattr(car, 'non_existent')#AttributeError: 'Car' object has no attribute 'non_existent'
# hasattr(obj,name)判断obj对象是否具备name属性，以bool类型作为返回值，能够避免AttributeError
# setattr(obj,name)为obj的name属性进行重新赋值，如果obj没有这个属性则添加
# delattr(obj,name)删除obj的name属性，如果obj没有这个属性会报错



'''运算符的重载'''
# 将自定义类型的实例可以像内建对象一样进行算术符运算
# 算术运算符
# 逻辑运算符
# 比较运算符
# 赋值运算符
# 位运算符
# __add__(self,rhs) self+rhs
# __sub__(self,rhs)   -
# __mul__(self,rhs)   *
# __truediv__(self,rhs) self/rhs
# __floordiv__(self,rhs) self//rhs 地板除
# __mod__(self,rhs) self%rhs
# __pow__(self,rhs) self**rhs

# 反向算数运算符
# __radd__(self,rhs) lsh+self
# __rsub__(self,rhs)   -
# __rmul__(self,rhs)   *
# __rtruediv__(self,rhs) /
# __rfloordiv__(self,rhs) // 地板除
# __rmod__(self,rhs) %
# __rpow__(self,rhs) **



# class MyNumber(object):
#     def __init__(self, data):
#         self.data = data
#     def __repr__(self):
#         return "MyNumber(%s)" % self.data
#     def __add__(self, other):
#         return self.data + other.data
#     def __sub__(self, other):
#         return self.data - other.data
#     def __mul__(self, other):
#         return self.data * other.data
#     def __truediv__(self, other):
#         return self.data / other.data
#     def __floordiv__(self, other):
#         return self.data // other.data
#     def __mod__(self, other):
#         return self.data % other.data
#     def __pow__(self, other):
#         return self.data ** other.data
#
# n1 = MyNumber(1)
# n2 = MyNumber(2)
# print(n1+n2)#重写__add__之前，不支持 unsupported operand


# class MyList():
#     def __init__(self,list):
#         self.list = list
#     # 当直接打印实例（如print(Mylist)）时，会调用 __repr__
#     def __repr__(self):#返回一个字符串
#         return "MyList %s" % self.list
#     def __add__(self,other):
#         #此处的 + 表拼接
#         # self.lis接收list1 other.list接收list2
#         return self.list + other.list
#     def __mul__(self,rhs):
#         return self.list * rhs
#     def __rmul__(self,lhs):
#         return self.list * lhs
# # class Add():
# #     def __init__(self,num1,num2):
# #         self.num1 = num1
# #         self.num2 = num2
# #     def __add__(self):
# #         result = [a + b for a, b in zip(self.num1, self.num2)]
# #         return MyList(result)  # 返回 MyList 对象
# #
# # L= Add([1,2,3,4,5],[6,7,8,9,10])
# # result = L.__add__()
# # print(result)
#
# list1 = MyList([1,2,3])
# list2 = MyList([4,5,6])
# # 调用 list1 的 __add__ 方法，并将 list2 作为参数传入
# print(list1 + list2)
# print(list1 * 2)
# print(2 * list1)
